﻿using DeHeng_Mes.Constant;
using DeHeng_Mes.Dao;
using DeHeng_Mes.Dao.PlcDao;
using DeHeng_Mes.Model;
using DeHeng_Mes.Model.Boss;
using DeHeng_Mes.Model.BossModel;
using DeHeng_Mes.Model.ConfigModel;
using DeHeng_Mes.Model.OrderSingleton;
using DeHeng_Mes.Model.Singleton;
using DeHeng_Mes.Model.Table;
using DeHeng_Mes.Utils;
using Newtonsoft.Json;
using NPOI.SS.Formula.Functions;
using Org.BouncyCastle.Asn1.Pkcs;
using S7.Net;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls.Primitives;
using System.Windows.Shapes;
using Path = System.IO.Path;

namespace DeHeng_Mes.Service
{
    public class PlcServicees
    {
        #region 成员实例
        PlcDao plcDao = new PlcDao();
        ProductionPowerDao productionPowerDao = new ProductionPowerDao();
        List<PlcOrderConfigModel> readPlcList = PlcOrderConfigModelList.ReadPlcList;
        #endregion

        public void GetPowerAndProdution(bool isTimer)
        {
            // 检查连接状态并查询工单
            foreach (var item in PlcConnectionManager.plcContainer)
            {
                // 未连接跳出本层
                if (!item.isConnected)
                    continue;

                // 获取Plc数据
                Dictionary<object, Type> dictionary = MappingTable.PlcMapping(item.plc, item.name);

                // 获取当前日期
                DateTime currentDate = DateTime.Now;

                // 获取天
                DateTime previousDate = isTimer ? currentDate.AddDays(-1) : currentDate;

                string day = previousDate.Day.ToString();

                // 获取当前年月日
                string date = $"{previousDate.Year}{previousDate.Month:D2}{previousDate.Day:D2}";

                // 判断当前plcName，执行不同方法
                switch (item.name)
                {
                    case "DOOR-01":
                        break;
                    case "DOOR-02":
                        Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();

                        // 执行当日产量采集
                        keyValuePairs.Add("L", plcDao.GetStringFieldValue(dictionary, "Production", "LRealTimeProduction"));
                        keyValuePairs.Add("R", plcDao.GetStringFieldValue(dictionary, "Production", "RRealTimeProduction"));

                        // 存入当天产量数据
                        foreach (var production in keyValuePairs)
                        {
                            // 判断产量数据是否保存
                            if (productionPowerDao.ProductionIsSave(item.name, date, production))
                                // 执行更新操作
                                productionPowerDao.UpdateProduction(item.name, date, production);
                            else
                                //执行插入操作
                                productionPowerDao.ProductionSave(item.name, date, production);
                        }
                        break;
                }

                // 执行当日能耗采集
                string power = plcDao.GetStringFieldValue(dictionary, "Power", "RealTimePower");

                // 存入当天能耗数据
                if (!string.IsNullOrEmpty(power))
                {
                    // 判断能耗数据是否保存
                    if (productionPowerDao.PowerIsSave(item.name, date, power))
                        // 执行更新操作
                        productionPowerDao.UpdatePower(item.name, date, power);
                    else
                        //执行插入操作
                        productionPowerDao.PowerSave(item.name, date, power);
                }
            }
        }

        /// <summary>
        /// 0点监控
        /// </summary>
        public async Task Timer()
        {
            Tools.ProduceLogText("零点监控线程启动成功！");

            while (true)
            {
                // 获取当前时间
                DateTime now = DateTime.Now;

                // 判断是否为凌晨0点
                // 判断是否为凌晨0点
                if (now.Hour == 0 && now.Minute == 0 && now.Second == 0)
                {
                    GetPowerAndProdution(true);
                }
                await Task.Delay(200);
            }
        }

        /// <summary>
        /// 来料管控
        /// </summary>
        /// <returns></returns>
        public async Task PartResult()
        {
            Tools.ProduceLogText("来料管控线程启动成功");

            while (true)
            {
                if (PlcConnectionManager.plcContainer != null && PlcConnectionManager.plcContainer.Count > 0)
                {
                    foreach (var plcConfig in PlcConnectionManager.plcContainer)
                    {
                        string plcName = plcConfig.name;

                        try
                        {
                            if (plcConfig.isConnected)
                            {
                                // 获取Plc数据实例与实例类型
                                Dictionary<object, Type> obj = MappingTable.PlcMapping(plcConfig.plc, plcName);

                                Dictionary<string, object> partCodeData = plcDao.GetFieldValues(obj, "QRResult");

                                foreach (var partCode in partCodeData)
                                {
                                    // 获取二维码
                                    string codeValue = PlcDao.ParseS7String((byte[])partCode.Value).Split(' ')[0];

                                    if (!string.IsNullOrEmpty(codeValue))
                                    {
                                        // 获取工单数据
                                        List<OrderSingletonModel> orderModels = OrderSingleton.Instance;

                                        string LR = partCode.Key[0].ToString();

                                        string materialId = LR.Equals("L") ? "B04055698600" : "A04055698600";

                                        if (orderModels?.Count > 0)
                                        {
                                            foreach (var orderModel in orderModels)
                                            {
                                                if (orderModel.MaterialId.Equals(materialId))
                                                {
                                                    // 调用工厂接口
                                                    HttpResult httpResult = await ApiUtil.SendJsonRequestAsync("http://10.18.16.34:8844/action/test", new BossPartData()
                                                    {
                                                        barcode = codeValue.Trim(),
                                                        wo_code = orderModel.OrderId,
                                                    });

                                                    if (httpResult.IsSuccess)
                                                    {
                                                        // 创建Plc空实例
                                                        S7.Net.Plc plcInit = plcConfig.plc;

                                                        // 解析数据
                                                        string responseJson = httpResult.ResponseJson;

                                                        BossPartDataReturn bossPartDataReturn = JsonConvert.DeserializeObject<BossPartDataReturn>(responseJson);

                                                        string code = bossPartDataReturn.code;

                                                        string count = bossPartDataReturn.qty;

                                                        string material_id = bossPartDataReturn.material_id;

                                                        // 初始化返回值
                                                        byte result = code.Equals("1") ? byte.Parse(code) : byte.Parse("2");

                                                        // 获取Plc对应字段的映射
                                                        int off = MappingTable.GetPartResultOff(plcName, partCode.Key);

                                                        // 判断是否是压铆
                                                        if (partCode.Key.Contains("Clinch"))
                                                        {
                                                            string clinchPlcName = LR.Equals("L") ? "DOOR-03" : "DOOR-04";

                                                            foreach (var clinchPlcConfig in PlcConnectionManager.plcContainer)
                                                            {
                                                                if (clinchPlcName.Equals(clinchPlcConfig.name))
                                                                {
                                                                    OrderSingleton.AddBatch(orderModel.OrderId, codeValue);

                                                                    plcInit = clinchPlcConfig.plc;

                                                                    off = 1;
                                                                }
                                                            }
                                                        }

                                                        // 将结果值反馈给Plc
                                                        plcInit.Write(DataType.DataBlock, 6005, off == 1 ? 0 : ((off - 1) * 260), result);

                                                        // 反馈数量
                                                        plcInit.Write(DataType.DataBlock, 6005, off == 1 ? 258 : 258 + ((off - 1) * 260), short.Parse(count));

                                                        // 反馈物料编号
                                                        plcInit.WriteBytes(DataType.DataBlock, 6005, off == 1 ? 2 : 2 + ((off - 1) * 260), Tools.ConvertToPlcString(material_id, material_id.Length));

                                                        Tools.ProduceLogText($"获取码{codeValue}并且返回了PLC结果为1");
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Tools.ProduceLogTextError($"{plcName}来料管控线程异常，原因是{ex.Message}");
                        }
                    }
                }

                await Task.Delay(200);
            }
        }

        /// <summary>
        /// 读取CSV文件
        /// </summary>
        /// <returns></returns>
        public async Task ReadCSVData()
        {
            Tools.ProduceLogText("拉铆数据轮询线程启动成功!");

            OrderDao orderDao = new OrderDao();

            Dictionary<string, string> dic = new Dictionary<string, string>()
                    {
                        { "RIVET_LEFT","192.168.12.209"},
                        { "RIVET_RIGHT","192.168.12.210"},
                        { "RIVET_PLC2","192.168.13.209"},
                        { "CLINCH_LEFT","192.168.12.55"},
                        { "CLINCH_RIGHT","192.168.12.55"},
                        { "CCD","192.168.13.180"},
                    };


            foreach (var filePaths in dic)
            {
                try
                {
                    await CsvConnection(filePaths.Key, filePaths.Value, orderDao);
                }
                catch (Exception ex)
                {
                    Tools.ProduceLogText($"[{filePaths.Key}:{filePaths.Value}]读取并保存CSV数据发生异常：原因是：{ex.Message}");
                }

                await Task.Delay(5000);
            }
        }

        /// <summary>
        /// Csv文件读取
        /// </summary>
        /// <param name="operation"></param>
        /// <param name="path"></param>
        /// <param name="orderDao"></param>
        private async Task CsvConnection(string operation, string pathIp, OrderDao orderDao)
        {
            switch (operation)
            {
                case "RIVET_LEFT":
                    await RivetConnection(pathIp, orderDao);
                    break;
                case "RIVET_RIGHT":
                    await RivetConnection(pathIp, orderDao);
                    break;
                case "RIVET_PLC2":
                    await RivetConnection(pathIp, orderDao);
                    break;
                case "CLINCH_LEFT":
                    await ClinchConnection(pathIp, orderDao);
                    break;
                case "CLINCH_RIGHT":
                    await ClinchConnection(pathIp, orderDao);
                    break;
                case "CCD":
                    await CCDConnection(pathIp, orderDao);
                    break;
            }
        }

        /// <summary>
        /// CCD文件读取
        /// </summary>
        /// <param name="pathIp"></param>
        /// <param name="orderDao"></param>
        private async Task CCDConnection(string pathIp, OrderDao orderDao)
        {
            foreach (var LR in new[] { "L", "R" })
            {
                var now = DateTime.Now;

                string directory = Path.Combine(
                    $@"\\{pathIp}\csv",
                    LR,
                    now.ToString("yyyy"),
                    now.ToString("MM"),
                    now.ToString("dd")
                );

                using (new NetworkConnection(Path.GetDirectoryName($@"\\{pathIp}\csv\"), new NetworkCredential("Administrator", "asd")))
                {
                    while (true)
                    {
                        if (Directory.Exists(directory))
                        {

                            try
                            {
                                // 获取目录下所有CSV文件路径
                                string[] csvFiles = Directory.GetFiles(directory, "*.csv");

                                foreach (string filePath in csvFiles)
                                {
                                    if (filePath.Contains("_Save"))
                                        continue;

                                    // 提取文件名和扩展名
                                    string fileName = Path.GetFileNameWithoutExtension(filePath);
                                    string extension = Path.GetExtension(filePath); // 如 ".csv"

                                    // 构建新文件名：原文件名 + "_Save" + 扩展名
                                    string newFileName = $"{fileName}_Save{extension}";
                                    string newFilePath = Path.Combine(Path.GetDirectoryName(filePath), newFileName);

                                    // 调用方法读取文件数据
                                    Dictionary<string, string[]> csvData = await CsvReaderHelper.ReadCsv(filePath, "测点名称");

                                    // 实例化存储类
                                    TraceCCD traceCCD = new TraceCCD();

                                    string[] parts = fileName.Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);

                                    string code = parts[parts.Length - 1].Split('_')[0];

                                    traceCCD.TraceId = code;

                                    // 循环存储
                                    for (int i = 0; i <= csvData["测点名称"].Length - 1; i++)
                                    {
                                        traceCCD.Result = csvData["Result"][i];

                                        traceCCD.PointName = csvData["测点名称"][i];

                                        // 调用存储
                                        if (!orderDao.CCDDataIsSave(code, traceCCD.PointName))
                                            orderDao.SaveCCDData(traceCCD);
                                    }

                                    Tools.ProduceLogText($"成功保存{csvData["测点名称"].Length}条CCD数据，关联码为[{traceCCD.TraceId}]");

                                    try
                                    {
                                        // 重命名文件（如果已存在则跳过或覆盖）
                                        if (!File.Exists(newFilePath))
                                        {
                                            File.Move(filePath, newFilePath);
                                        }
                                        else
                                        {
                                            Tools.ProduceLogTextError($"文件已存在，跳过: {newFileName}");

                                            File.Delete(filePath);
                                        }
                                    }
                                    catch (IOException ex)
                                    {
                                        Tools.ProduceLogTextError($"标签打入失败: {ex.Message}");
                                    }
                                }
                            }
                            catch (DirectoryNotFoundException)
                            {
                                Tools.ProduceLogTextError($"CCD数据文件目录不存在: {directory}");
                            }
                            catch (UnauthorizedAccessException)
                            {
                                Tools.ProduceLogTextError("CCD数据文件没有访问权限，请检查凭据。");
                            }
                            catch (Exception ex)
                            {
                                Tools.ProduceLogTextError($"CCD数据文件读取发生错误: {ex.Message}");
                            }
                        }

                        await Task.Delay(2000);
                    }
                }
            }
        }

        /// <summary>
        /// 压铆文件读取
        /// </summary>
        /// <param name="pathIp"></param>
        /// <param name="orderDao"></param>
        private async Task ClinchConnection(string pathIp, OrderDao orderDao)
        {
            // 初始化日期
            string date = $"{DateTime.Now.ToString("yyyy")}{DateTime.Now.ToString("MM")}{DateTime.Now.ToString("dd")}";

            // 初始化文件夹路径
            string directory = $@"\\{pathIp}\ym\before\Data_info\{date}\{date}";

            using (new NetworkConnection(Path.GetDirectoryName(@"\\192.168.12.55\ym\"), new NetworkCredential("CTOS", "asd")))
            {
                while (true)
                {
                    if (Directory.Exists(directory))
                    {

                        try
                        {
                            // 获取目录下所有CSV文件路径
                            string[] csvFiles = Directory.GetFiles(directory, "*.csv");

                            foreach (string filePath in csvFiles)
                            {
                                if (filePath.Contains("_Save"))
                                    continue;

                                // 提取文件名和扩展名
                                string fileName = Path.GetFileNameWithoutExtension(filePath);
                                string extension = Path.GetExtension(filePath); // 如 ".csv"

                                // 构建新文件名：原文件名 + "_Save" + 扩展名
                                string newFileName = $"{fileName}_Save{extension}";
                                string newFilePath = Path.Combine(Path.GetDirectoryName(filePath), newFileName);

                                // 调用方法读取文件数据
                                Dictionary<string, string[]> csvData = await CsvReaderHelper.ReadCsv(filePath, "零件二维码");

                                // 实例化存储类
                                TraceClinch traceClinch = new TraceClinch();

                                // 循环存储
                                for (int i = 0; i <= csvData["零件二维码"].Length - 1; i++)
                                {
                                    traceClinch.Result = csvData["单次结果"][i];

                                    traceClinch.DataTime = $"{csvData["日期"][i]} {csvData["时间"][i]}";

                                    traceClinch.Pressure = csvData["压力 "][i];

                                    traceClinch.PressureMax = csvData["压力上限"][i];

                                    traceClinch.PressureMin = csvData["压力下限 "][i];

                                    traceClinch.Displacement = csvData["位移"][i];

                                    traceClinch.DisplacementMax = csvData["位移上限"][i];

                                    traceClinch.DisplacementMin = csvData["位移下限"][i];

                                    traceClinch.TraceId = csvData["零件二维码"][i];

                                    traceClinch.PointNo = csvData["点位编号"][i];

                                    traceClinch.PointCount = csvData["点位计数 "][i];

                                    traceClinch.ToolNo = csvData["程序号"][i];

                                    traceClinch.Station = csvData["工位号"][i];

                                    // 调用存储
                                    if (!orderDao.ClinchDataIsSave(traceClinch.TraceId, traceClinch.PointCount, traceClinch.Station))
                                        orderDao.SaveClinchData(traceClinch);
                                }

                                Tools.ProduceLogText($"成功保存{csvData["零件二维码"].Length}条压铆数据，关联码为[{traceClinch.TraceId}],工位[{traceClinch.Station}]");

                                try
                                {
                                    // 重命名文件（如果已存在则跳过或覆盖）
                                    if (!File.Exists(newFilePath))
                                    {
                                        File.Move(filePath, newFilePath);
                                    }
                                    else
                                    {
                                        Tools.ProduceLogTextError($"文件已存在，跳过: {newFileName}");

                                        File.Delete(filePath);
                                    }
                                }
                                catch (IOException ex)
                                {
                                    Tools.ProduceLogTextError($"标签打入失败: {ex.Message}");
                                }
                            }
                        }
                        catch (DirectoryNotFoundException)
                        {
                            Tools.ProduceLogTextError($"压铆数据文件目录不存在: {directory}");
                        }
                        catch (UnauthorizedAccessException)
                        {
                            Tools.ProduceLogTextError("压铆数据文件没有访问权限，请检查凭据。");
                        }
                        catch (Exception ex)
                        {
                            Tools.ProduceLogTextError($"压铆数据文件读取发生错误: {ex.Message}");
                        }
                    }

                    await Task.Delay(2000);
                }
            }
        }

        /// <summary>
        /// 拉铆文件读取
        /// </summary>
        /// <param name="path"></param>
        /// <param name="orderDao"></param>
        private async Task RivetConnection(string pathIp, OrderDao orderDao)
        {
            DateTime now = DateTime.Now;

            int year = now.Year;

            string month = now.Month.ToString().Length > 1 ? now.Month.ToString() : "0" + now.Month.ToString();

            string day = now.Day.ToString().Length > 1 ? now.Day.ToString() : "0" + now.Day.ToString();

            // 初始化文件夹路径
            string directory = $@"\\{pathIp}\data\Data_Info\{year}{month}\{year}{month}{day}";

            using (new NetworkConnection(Path.GetDirectoryName($@"\\{pathIp}\data\"), new NetworkCredential("ADMIN", "asd")))
            {
                while (true)
                {
                    if (Directory.Exists(directory))
                    {
                        try
                        {
                            // 获取目录下所有CSV文件路径
                            string[] csvFiles = Directory.GetFiles(directory, "*.csv");

                            foreach (string filePath in csvFiles)
                            {
                                if (filePath.Contains("_IsSave"))
                                    continue;

                                // 提取文件名和扩展名
                                string fileName = Path.GetFileNameWithoutExtension(filePath);
                                string extension = Path.GetExtension(filePath); // 如 ".csv"

                                // 构建新文件名：原文件名 + "_Save" + 扩展名
                                string newFileName = $"{fileName}_IsSave{extension}";
                                string newFilePath = Path.Combine(Path.GetDirectoryName(filePath), newFileName);

                                // 调用方法读取文件数据
                                Dictionary<string, string[]> csvData = await CsvReaderHelper.ReadCsv(filePath, "钉子二维码");

                                // 实例化存储类
                                TraceRivete traceRivete = new TraceRivete();

                                // 循环存储
                                for (int i = 0; i <= csvData["二维码"].Length - 1; i++)
                                {

                                    traceRivete.Result = csvData["结果"][i];

                                    traceRivete.DataTime = $"{csvData["日期"][i]}";

                                    traceRivete.Pulling = csvData["拉力"][i];

                                    traceRivete.PullingMax = csvData["拉力上限"][i];

                                    traceRivete.PullingMin = csvData["拉力下限"][i];

                                    traceRivete.Displacement = csvData["位移"][i];

                                    traceRivete.DisplacementMax = csvData["位移上限"][i];

                                    traceRivete.DisplacementMin = csvData["位移下限"][i];

                                    traceRivete.TraceId = csvData["二维码"][i].Equals("null") ? csvData["批次"][i] : csvData["二维码"][i];

                                    traceRivete.PointNo = csvData["点位编号"][i];

                                    traceRivete.PointCount = csvData["点位计数"][i];

                                    traceRivete.ToolNo = csvData["枪号"][i];

                                    traceRivete.Station = csvData["工位"][i];

                                    // 调用存储
                                    if (!orderDao.RiveteDataIsSave(traceRivete.TraceId, traceRivete.PointCount, traceRivete.Station))
                                        orderDao.SaveRiveteData(traceRivete);
                                }

                                Tools.ProduceLogText($"成功保存{csvData["二维码"].Length}条拉铆数据，关联码为[{traceRivete.TraceId}],工位[{traceRivete.Station}]");

                                try
                                {
                                    // 重命名文件（如果已存在则跳过或覆盖）
                                    if (!File.Exists(newFilePath))
                                    {
                                        File.Move(filePath, newFilePath);
                                    }
                                    else
                                    {
                                        Tools.ProduceLogTextError($"文件已存在，跳过: {newFileName}");

                                        File.Delete(filePath);
                                    }
                                }
                                catch (IOException ex)
                                {
                                    Tools.ProduceLogTextError($"标签打入失败: {ex.Message}");
                                }
                            }
                        }
                        catch (DirectoryNotFoundException)
                        {
                            Tools.ProduceLogTextError($"拉铆数据文件目录不存在: {directory}");
                        }
                        catch (UnauthorizedAccessException)
                        {
                            Tools.ProduceLogTextError("拉铆数据文件没有访问权限，请检查凭据。");
                        }
                        catch (Exception ex)
                        {
                            Tools.ProduceLogTextError($"拉铆数据文件读取发生错误: {ex.Message}");
                        }
                    }
                    else
                    {
                        // 文件夹不存在
                        Tools.ProduceLogText($"拉铆数据文件夹未生成");
                    }

                    await Task.Delay(2000);
                }
            }
        }
    }
}
